const tokenHelper = appRequire('common/tokenHelper');
const courseDetailCache = appRequire('common/courseDetailCache');
const thisRequest = require('sync-request');
const {
	Op
} = require('sequelize');

// 引入模型
const baiduCourseModel = appRequire('models/baiduCourse');
const userModel = appRequire('models/user');

// 导出对象，供其它模块调用
module.exports = {
    list,
    detail,
    search,
    getBaiduLink,
    clearCourseDetailCache,
    getCourseDetailCacheStats
};

/**
 * 获取百度网盘课程列表（从数据库查询）
 * 文件夹名称 = 课程名称
 */
async function list(req, request) {
    let postData = req.body;
    let returnData = Common.clone(Constant.DEFAULT_SUCCESS);

    try {
        // 分页参数
        const pageNum = postData.pageNum || 1;
        const pageSize = postData.pageSize || 20;

        console.log('📁 正在从数据库获取课程列表:', `页码${pageNum}, 每页${pageSize}条`);

        // 查询数据库
        const result = await baiduCourseModel.findAndCountAll({
            where: {
                isVisible: true // 只查询可见的课程
            },
            order: [
                ['order', 'DESC'],
                ['name', 'ASC']
            ],
            offset: (pageNum - 1) * pageSize,
            limit: pageSize
        });

        console.log(`✅ 成功从数据库获取 ${result.rows.length} 个课程 (总数${result.count})`);

        // 映射为前端需要的数据结构
        const courses = result.rows.map(course => {
            return {
                objectId: course.fs_id, // 使用fs_id作为唯一标识
                name: course.displayName || course.name, // 优先使用显示名称
                title: course.displayName || course.name,
                path: course.path, // 完整路径
                order: course.order, // 排序序号
                createTime: formatTimestamp2(course.createTime), // 创建时间
                updateTime: formatTimestamp2(course.updateTime), // 修改时间
                folderInfo: course.folderInfo ? JSON.parse(course.folderInfo) : {
                    fs_id: course.fs_id,
                    path: course.path,
                    server_filename: course.name
                }
            };
        });

        const responseData = {
            total: result.count,
            list: courses,
            pageNum: pageNum,
            pageSize: pageSize
        };

        returnData.code = 1;
        returnData.data = responseData;
        request.json(returnData);

    } catch (error) {
        console.error('❌ 获取课程列表失败:', error);
        returnData.msg = error.message || '获取课程列表失败';
        returnData.code = -1;
        request.json(returnData);
    }
}

/**
 * 获取课程详情（文件夹下的文件列表，使用listall接口递归获取）
 * 文件列表 = 课件列表
 */
async function detail(req, request) {
    let postData = req.body;
    let returnData = Common.clone(Constant.DEFAULT_SUCCESS);

    // 检查必填参数
    let checkResult = Common.checkUrl(postData, ['path'], request);
    if (checkResult == false) return;

    try {
        const coursePath = postData.path;
        const recursion = postData.recursion || 1; // 默认递归获取

        // 检查是否有缓存
        const cachedData = courseDetailCache.getCourseDetail(coursePath);
        if (cachedData) {
            returnData.data = cachedData;
            returnData.fromCache = true; // 标记数据来自缓存
            return request.json(returnData);
        }

        // 从数据库获取百度网盘token
        const access_token = await tokenHelper.getBaiduToken();

        // 调用百度网盘API获取文件列表（使用listall接口，支持重试）
        const baiduApi = "http://pan.baidu.com/rest/2.0/xpan/multimedia";
        const url = `${baiduApi}?method=listall&access_token=${access_token}&path=${encodeURIComponent(coursePath)}&recursion=${recursion}&order=name&desc=0&limit=1000&web=1`;

        console.log('📄 正在获取课程详情（递归）:', coursePath);

        let jsonObj;
        let retryCount = 0;
        const maxRetries = 2; // 最多重试2次

        while (retryCount <= maxRetries) {
            try {
                var res = thisRequest('GET', url, {
                    headers: {
                        'User-Agent': 'pan.baidu.com'
                    }
                });

                var body = res.getBody();
                jsonObj = JSON.parse(body);

                // 检查是否命中频率限制
                if (jsonObj.errno === 31034) {
                    if (retryCount < maxRetries) {
                        const waitTime = (retryCount + 1) * 3000; // 第一次等3秒，第二次等6秒
                        console.log(`⚠️ 命中频率限制 (31034)，等待 ${waitTime/1000} 秒后重试... (${retryCount + 1}/${maxRetries})`);
                        await new Promise(resolve => setTimeout(resolve, waitTime));
                        retryCount++;
                        continue;
                    } else {
                        console.error('❌ 重试次数已达上限，仍然命中频率限制');
                        returnData.msg = '请求过于频繁，请稍后再试';
                        returnData.code = -1;
                        return request.json(returnData);
                    }
                }

                // 其他错误直接返回
                if (jsonObj.errno !== 0) {
                    console.error('❌ 百度网盘API返回错误:', jsonObj);
                    returnData.msg = jsonObj.errmsg || '获取课程详情失败';
                    returnData.code = -1;
                    return request.json(returnData);
                }

                // 成功，跳出循环
                break;

            } catch (error) {
                // 如果是网络错误且还有重试次数
                if (retryCount < maxRetries && error.statusCode === 400) {
                    const waitTime = (retryCount + 1) * 3000;
                    console.log(`⚠️ 请求失败，等待 ${waitTime/1000} 秒后重试... (${retryCount + 1}/${maxRetries})`);
                    await new Promise(resolve => setTimeout(resolve, waitTime));
                    retryCount++;
                    continue;
                } else {
                    throw error; // 重新抛出错误
                }
            }
        }

        // 支持的文件格式
        const supportedExtensions = ['ppt', 'pptx', 'pdf', 'doc', 'docx','png','jpg','jepg','mov','mp4'];

        // 分别获取文件夹和文件
        const allFiles = jsonObj.list || [];
        const folders = allFiles.filter(item => item.isdir === 1);
        const files = allFiles.filter(item => {
            if (item.isdir === 1) return false; // 排除文件夹

            // 检查文件扩展名
            const filename = (item.server_filename || '').toLowerCase();
            const hasValidExt = supportedExtensions.some(ext =>
                filename.endsWith('.' + ext)
            );

            return hasValidExt;
        });

        console.log(`✅ 成功获取 ${folders.length} 个子文件夹, ${files.length} 个课件文件 (has_more: ${jsonObj.has_more})`);

        // 映射文件夹数据结构
        const subFolders = folders.map(folder => {
            return {
                objectId: folder.fs_id.toString(),
                name: folder.server_filename,
                title: folder.server_filename,
                path: folder.path,
                createTime: formatTimestamp(folder.server_ctime),
                updateTime: formatTimestamp(folder.server_mtime),
                isFolder: true, // 标记为文件夹
                thumbs: folder.thumbs || '', // 缩略图
                folderInfo: {
                    fs_id: folder.fs_id,
                    path: folder.path,
                    server_filename: folder.server_filename,
                    isdir: folder.isdir,
                    category: folder.category || 0
                }
            };
        });

        // 映射为课件数据结构
        const coursewares = files.map((file, index) => {
            // 提取文件名（去除扩展名）
            let title = file.server_filename || '';
            title = title.replace(/\.(ppt|pptx|pdf|doc|docx)$/i, '');

            // 提取文件扩展名
            const extMatch = file.server_filename.match(/\.([^.]+)$/);
            const fileExt = extMatch ? extMatch[1].toLowerCase() : '';

            return {
                objectId: file.fs_id.toString(), // 使用fs_id作为唯一标识
                title: title,
                name: title,
                server_filename: file.server_filename,
                size: Common.getFileSize(file.size), // 格式化文件大小
                sizeRaw: file.size,
                createTime: formatTimestamp(file.server_ctime),
                updateTime: formatTimestamp(file.server_mtime),
                fileExt: fileExt,
                sortIndex: index + 1, // 顺序索引
                isFolder: false, // 标记为文件
                thumbs: file.thumbs || '', // 缩略图地址
                fileInfo: {
                    fs_id: file.fs_id,
                    path: file.path,
                    server_filename: file.server_filename,
                    size: file.size,
                    md5: file.md5 || '',
                    isdir: file.isdir,
                    category: file.category || 0
                }
            };
        });

        // 获取课程名称（从路径中提取）
        const courseName = coursePath.split('/').filter(Boolean).pop() || '未命名课程';

        const courseDetailData = {
            courseInfo: {
                name: courseName,
                title: courseName,
                path: coursePath,
                folderCount: subFolders.length,
                fileCount: coursewares.length,
                totalCount: subFolders.length + coursewares.length,
                hasMore: jsonObj.has_more || 0, // 是否还有下一页
                cursor: jsonObj.cursor || 0 // 下一页游标
            },
            folders: subFolders, // 子文件夹列表
            coursewares: coursewares, // 课件文件列表
            total: subFolders.length + coursewares.length
        };

        // 保存到缓存
        courseDetailCache.setCourseDetail(coursePath, courseDetailData);

        returnData.data = courseDetailData;
        returnData.fromCache = false; // 标记数据来自API

        request.json(returnData);

    } catch (error) {
        console.error('❌ 获取课程详情失败:', error);
        returnData.msg = error.message || '获取课程详情失败';
        returnData.code = -1;
        request.json(returnData);
    }
}

/**
 * 搜索百度网盘课程（从数据库搜索）
 * @param {Object} req 请求对象
 * @param {Object} request 响应对象
 */
async function search(req, request) {
    let postData = req.body;
    let returnData = Common.clone(Constant.DEFAULT_SUCCESS);

    // 检查必填参数
    let checkResult = Common.checkUrl(postData, ['keyword'], request);
    if (checkResult == false) return;

    try {
        const keyword = postData.keyword;
        const pageNum = postData.pageNum || 1;
        const pageSize = postData.pageSize || 20;

        console.log('🔍 正在从数据库搜索课程:', keyword);

        // 构建查询条件
        const where = {
            isVisible: true, // 只查询可见的课程
            [Op.or]: [
                {
                    name: {
                        [Op.like]: `%${keyword}%`
                    }
                },
                {
                    displayName: {
                        [Op.like]: `%${keyword}%`
                    }
                }
            ]
        };

        // 查询数据库
        const result = await baiduCourseModel.findAndCountAll({
            where,
            order: [
                ['order', 'DESC'],
                ['name', 'ASC']
            ],
            offset: (pageNum - 1) * pageSize,
            limit: pageSize
        });

        console.log(`✅ 搜索到 ${result.count} 个匹配的课程`);

        // 映射为前端需要的数据结构
        const courses = result.rows.map(course => {
            return {
                objectId: course.fs_id,
                name: course.displayName || course.name,
                title: course.displayName || course.name,
                path: course.path,
                order: course.order,
                createTime: formatTimestamp2(course.createTime),
                updateTime: formatTimestamp2(course.updateTime),
                folderInfo: course.folderInfo ? JSON.parse(course.folderInfo) : {
                    fs_id: course.fs_id,
                    path: course.path,
                    server_filename: course.name
                }
            };
        });

        const responseData = {
            total: result.count,
            list: courses,
            keyword: keyword,
            pageNum: pageNum,
            pageSize: pageSize
        };

        returnData.code = 1;
        returnData.data = responseData;
        request.json(returnData);

    } catch (error) {
        console.error('❌ 搜索课程失败:', error);
        returnData.msg = error.message || '搜索失败';
        returnData.code = -1;
        request.json(returnData);
    }
}

/**
 * 格式化时间戳（百度 API 返回的时间戳，单位：秒）
 * @param {number} timestamp 时间戳（秒）
 * @returns {string} 格式化的时间字符串
 */
function formatTimestamp(timestamp) {
    if (!timestamp) return '';

    const date = new Date(timestamp * 1000); // 转换为毫秒
    const year = date.getFullYear();
    const month = String(date.getMonth() + 1).padStart(2, '0');
    const day = String(date.getDate()).padStart(2, '0');
    const hour = String(date.getHours()).padStart(2, '0');
    const minute = String(date.getMinutes()).padStart(2, '0');
    const second = String(date.getSeconds()).padStart(2, '0');

    return `${year}-${month}-${day} ${hour}:${minute}:${second}`;
}

/**
 * 格式化日期对象（数据库中的 Date 对象）
 * @param {Date|string} date 日期对象或字符串
 * @returns {string} 格式化的时间字符串
 */
function formatTimestamp2(date) {
    if (!date) return '';

    const d = new Date(date);
    const year = d.getFullYear();
    const month = String(d.getMonth() + 1).padStart(2, '0');
    const day = String(d.getDate()).padStart(2, '0');
    const hour = String(d.getHours()).padStart(2, '0');
    const minute = String(d.getMinutes()).padStart(2, '0');
    const second = String(d.getSeconds()).padStart(2, '0');

    return `${year}-${month}-${day} ${hour}:${minute}:${second}`;
}

/**
 * 清除课程详情缓存
 * @param {Object} req 请求对象
 * @param {Object} request 响应对象
 */
async function clearCourseDetailCache(req, request) {
    let postData = req.body;
    let returnData = Common.clone(Constant.DEFAULT_SUCCESS);

    try {
        const coursePath = postData.path; // 可选参数，不传则清除所有缓存

        courseDetailCache.clearCache(coursePath);

        returnData.code = 1;
        returnData.msg = coursePath ? '指定课程缓存已清除' : '所有课程缓存已清除';
        request.json(returnData);

    } catch (error) {
        console.error('❌ 清除缓存失败:', error);
        returnData.msg = error.message || '清除缓存失败';
        returnData.code = -1;
        request.json(returnData);
    }
}

/**
 * 获取课程详情缓存统计
 * @param {Object} req 请求对象
 * @param {Object} request 响应对象
 */
async function getCourseDetailCacheStats(req, request) {
    let returnData = Common.clone(Constant.DEFAULT_SUCCESS);

    try {
        const stats = courseDetailCache.getCacheStats();

        returnData.code = 1;
        returnData.data = stats;
        request.json(returnData);

    } catch (error) {
        console.error('❌ 获取缓存统计失败:', error);
        returnData.msg = error.message || '获取缓存统计失败';
        returnData.code = -1;
        request.json(returnData);
    }
}

/**
 * 获取百度网盘课程分享链接
 * 需要验证用户会员状态
 */
async function getBaiduLink(req, request) {
    let postData = req.body;
    let returnData = Common.clone(Constant.DEFAULT_SUCCESS);

    // 检查必填参数
    let checkResult = Common.checkUrl(postData, ['path', 'uid'], request);
    if (checkResult == false) return;

    try {
        const coursePath = postData.path;

        // 查询用户信息（在clone前获取原始vipTime值）
        let thisUser = await userModel.user.findOne({
            where: {
                objectId: postData.uid
            }
        });

        // 在clone之前获取原始vipTime值用于判断
        const rawVipTime = thisUser ? thisUser.getDataValue('vipTime') : null;
        const isVip = rawVipTime && (rawVipTime == 4102416000000 || rawVipTime > new Date().getTime());

        if (!isVip) {
            returnData.msg = '非会员不能下载，请先开通会员';
            returnData.code = -1;
            return request.json(returnData);
        }

        console.log('📎 会员用户请求获取百度网盘链接:', coursePath);

        // 从数据库查询课程信息
        const course = await baiduCourseModel.findOne({
            where: {
                path: coursePath
            }
        });

        if (!course) {
            returnData.msg = '课程不存在';
            returnData.code = -1;
            return request.json(returnData);
        }

        const fs_id = course.fs_id;
        let baiduDeskLink = course.baiduDeskLink;

        console.log('📦 课程信息:', { name: course.name, fs_id });

        // 如果数据库中没有分享链接，则生成新的
        /*if (!baiduDeskLink) {
            console.log('⚠️  数据库中未找到分享链接，正在生成新链接...');

            // 从数据库获取百度网盘配置
            const bdstoken = await tokenHelper.getBaiduBdstoken();
            const logid = await tokenHelper.getBaiduLogid();
            const cookie = await tokenHelper.getBaiduCookie();

            // 调用百度API创建分享链接（参数在URL中）
            const url = `https://pan.baidu.com/share/set?channel=chunlei&bdstoken=${bdstoken}&clienttype=0&app_id=250528&web=1&dp-logid=${logid}&fid_list=[${fs_id}]&schannel=4&pwd=1090&period=0`;

            console.log('🔍 请求URL:', url);

            // 使用 thisRequest 发送请求，body 为空 json
            var res = thisRequest('POST', url, {
                json: {},
                headers: {
                    'User-Agent': 'pan.baidu.com',
                    'Content-Type': 'application/x-www-form-urlencoded',
                    'Cookie': cookie
                }
            });

            var body = res.getBody();
            var jsonObj = JSON.parse(body);

            console.log('📦 百度API返回:', jsonObj);

            if (!jsonObj || !jsonObj.link) {
                console.error('❌ 创建分享链接失败:', jsonObj);
                returnData.msg = '创建分享链接失败，请联系管理员';
                returnData.code = -1;
                return request.json(returnData);
            }

            baiduDeskLink = jsonObj.link;

            // 更新数据库，保存生成的链接
            await baiduCourseModel.update(
                { baiduDeskLink: baiduDeskLink },
                { where: { objectId: course.objectId } }
            );

            console.log('✅ 分享链接已生成并保存到数据库');
        } else {
            console.log('✅ 从数据库读取分享链接');
        }*/

        // 生成二维码图片URL
        const thisWords = baiduDeskLink.split("https://pan.baidu.com/s/");
        const shortUrl = thisWords[1] ? thisWords[1].replace("?", "&") : '';
        const baiduDeskImage = shortUrl ? `https://pan.baidu.com/api/wechat/qrcode?width=150&clienttype=0&shorturl=${shortUrl}` : '';

        returnData.code = 1;
        returnData.data = {
            baiduDeskLink: baiduDeskLink,
            baiduDeskImage: baiduDeskImage,
            link: baiduDeskLink,
            fs_id: fs_id
        };

        request.json(returnData);

    } catch (error) {
        console.error('❌ 获取百度网盘链接失败:', error);
        returnData.msg = error.message || '获取链接失败';
        returnData.code = -1;
        request.json(returnData);
    }
}
